Variables categóricas: Gráficos

R para Ciencia de Datos en Salud:
Análisis Descriptivo e Inferencia Estadística

Percy Soto-Becerra M.D., M.Sc(c)

InkaStats Data Science Solutions | Medical Branch
@github/psotob91

Gráficas de variables categóricas con R

¿Qué graficos podemos hacer para visualizar variables categóricas?

  • Se pueden hacer una infinidad de estos.

  • El más común para investigación científica es el gráfico de barras.

  • Una gráfico menos usado en investigación científica, pero sí en reportes o presentaciones podría ser el gráfico de pái.

  • Otros gráficos interesantes:

Gráfico de barras

Estructura de datos para gráfico de barras


Datos individuales:
geom_bar()
vs.
Datos agrupados:
geom_bar(stat = “identity”) o
geom_col()

Gráfico de barras de frecuencias absolutas

Para estos gráficos vamos a trabajar con los datos de pacientes hospitalizados durante una pandemia de Ébola. Los datos pertenecen al libro The Epidemiologist Handbook descrito en la sección del Syllabus.

  • Importamos y exploramos los datos que están en formato de R: *.rds
ebola_data <- import("linelist_cleaned.rds")
ebola_data %>% 
  glimpse()
Rows: 5,888
Columns: 30
$ case_id              <chr> "5fe599", "8689b7", "11f8ea", "b8812a", "893f25",…
$ generation           <dbl> 4, 4, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 6, 5, 6, 9, 1…
$ date_infection       <date> 2014-05-08, NA, NA, 2014-05-04, 2014-05-18, 2014…
$ date_onset           <date> 2014-05-13, 2014-05-13, 2014-05-16, 2014-05-18, …
$ date_hospitalisation <date> 2014-05-15, 2014-05-14, 2014-05-18, 2014-05-20, …
$ date_outcome         <date> NA, 2014-05-18, 2014-05-30, NA, 2014-05-29, 2014…
$ outcome              <chr> NA, "Recover", "Recover", NA, "Recover", "Recover…
$ gender               <chr> "m", "f", "m", "f", "m", "f", "f", "f", "m", "f",…
$ age                  <dbl> 2, 3, 56, 18, 3, 16, 16, 0, 61, 27, 12, 42, 19, 7…
$ age_unit             <chr> "years", "years", "years", "years", "years", "yea…
$ age_years            <dbl> 2, 3, 56, 18, 3, 16, 16, 0, 61, 27, 12, 42, 19, 7…
$ age_cat              <fct> 0-4, 0-4, 50-69, 15-19, 0-4, 15-19, 15-19, 0-4, 5…
$ age_cat5             <fct> 0-4, 0-4, 55-59, 15-19, 0-4, 15-19, 15-19, 0-4, 6…
$ hospital             <chr> "Other", "Missing", "St. Mark's Maternity Hospita…
$ lon                  <dbl> -13.21574, -13.21523, -13.21291, -13.23637, -13.2…
$ lat                  <dbl> 8.468973, 8.451719, 8.464817, 8.475476, 8.460824,…
$ infector             <chr> "f547d6", NA, NA, "f90f5f", "11f8ea", "aec8ec", "…
$ source               <chr> "other", NA, NA, "other", "other", "other", "othe…
$ wt_kg                <dbl> 27, 25, 91, 41, 36, 56, 47, 0, 86, 69, 67, 84, 68…
$ ht_cm                <dbl> 48, 59, 238, 135, 71, 116, 87, 11, 226, 174, 112,…
$ ct_blood             <dbl> 22, 22, 21, 23, 23, 21, 21, 22, 22, 22, 22, 22, 2…
$ fever                <chr> "no", NA, NA, "no", "no", "no", NA, "no", "no", "…
$ chills               <chr> "no", NA, NA, "no", "no", "no", NA, "no", "no", "…
$ cough                <chr> "yes", NA, NA, "no", "yes", "yes", NA, "yes", "ye…
$ aches                <chr> "no", NA, NA, "no", "no", "no", NA, "no", "no", "…
$ vomit                <chr> "yes", NA, NA, "no", "yes", "yes", NA, "yes", "ye…
$ temp                 <dbl> 36.8, 36.9, 36.9, 36.8, 36.9, 37.6, 37.3, 37.0, 3…
$ time_admission       <chr> NA, "09:36", "16:48", "11:22", "12:60", "14:13", …
$ bmi                  <dbl> 117.18750, 71.81844, 16.06525, 22.49657, 71.41440…
$ days_onset_hosp      <dbl> 2, 1, 2, 2, 1, 1, 2, 1, 1, 2, 2, 2, 1, 0, 2, 0, 1…
  • Distribución de pacientes según hospital tabyl()
ebola_data %>% 
  tabyl(hospital)
                             hospital    n    percent
                     Central Hospital  454 0.07710598
                    Military Hospital  896 0.15217391
                              Missing 1469 0.24949049
                                Other  885 0.15030571
                        Port Hospital 1762 0.29925272
 St. Mark's Maternity Hospital (SMMH)  422 0.07167120
  • Distribución de pacientes sin datos faltantes tabyl()
ebola_data %>% 
  filter(hospital != "Missing") %>% 
  tabyl(hospital)
                             hospital    n    percent
                     Central Hospital  454 0.10273818
                    Military Hospital  896 0.20276081
                                Other  885 0.20027155
                        Port Hospital 1762 0.39873274
 St. Mark's Maternity Hospital (SMMH)  422 0.09549672

Usamos geom_bar() cuando queremos que la altura de la barra refleje el número de filas relevantes en los datos. Por defecto, las barras son de frecuencias absolutas y se llaman count.

Barplot vertical

ebola_data %>% 
  ggplot(aes(x = hospital)) + 
  geom_bar()

Barplot horizontal

ebola_data %>% 
  ggplot(aes(y = hospital)) + 
  geom_bar()

Usamos geom_col() cuando queremos que la altura de la barra refleje valores pre-calculados que existen en los datos. A menudo, los datos son agregads y pueden obtenerse mediante la combinación summarise() y group_by().

  • Te proprocionan una tabla de datos agregada (no tienes valores individuales), solo los totales de casos y6 su prevalencia:
  nivel_dolor casos prevalencia
1        Leve   234        61.9
2    Moderado   123        32.5
3      Severo    21         5.6
  • Puedes graficarlo usando geom_col() que no requiere datos individuales.
datos_agregados %>% 
  ggplot(aes(x = nivel_dolor, y = casos)) + 
  geom_col()

geom_col() y geom_bar() son equivalentes.

datos_agregados %>% 
  ggplot(aes(x = nivel_dolor, y = casos)) + 
  geom_col()

datos_agregados %>% 
  ggplot(aes(x = nivel_dolor, y = casos)) + 
  geom_bar(stat = "identity")

Si tenemos datos individuales, podemos agregarlos y así resulta más fácil pensar en los gráficos de barras desde ggplot()

ebola_data %>% 
  group_by(hospital) %>% 
  count() %>% 
  ggplot(aes(x = n, y = hospital)) + 
  geom_col()

ebola_data %>% 
  group_by(hospital) %>% 
  count() %>% 
  ggplot(aes(x = n, y = hospital)) + 
  geom_bar(stat = "identity")

Cambiar el orden de las barras arbitrariamente

ebola_data %>% 
  mutate(
    hospital = fct_relevel(hospital, 
                           "St. Mark's Maternity Hospital (SMMH)", 
                           "Port Hospital", 
                           "Central Hospital",
                           "Military Hospital",
                           "Other",
                           "Missing")
    ) %>% 
  ggplot(aes(y = hospital)) + 
  geom_bar()

Editar etiquetas y tema

ebola_data %>% 
  mutate(
    hospital = fct_relevel(hospital, 
                           "St. Mark's Maternity Hospital (SMMH)", "Port Hospital", 
                           "Central Hospital", "Military Hospital", "Other",
                           "Missing")
    ) %>% 
  ggplot(aes(y = hospital)) + 
  geom_bar() + 
  labs(x = "Frecuencia absoluta", y = "Hospitales") + 
  theme_bw()

Gráfico de barras de frecuencias relativas

Las frecuencias relativas necesitan ser calculadas para reportarse. La forma más fácil de hacerlo es agregando los datos mediante el uso de count(). Luego usamos mutate() para crear las proporciones o porcentajes. También podemos trabajar con datos individuales, pero el código puede verse un poco más duro.

  • Agregamos los datos de hospitalizados
ebola_data %>% 
  count(hospital)
                              hospital    n
1                     Central Hospital  454
2                    Military Hospital  896
3                              Missing 1469
4                                Other  885
5                        Port Hospital 1762
6 St. Mark's Maternity Hospital (SMMH)  422
  • Creamos la columna de porcentaje:
ebola_data %>% 
  count(hospital) %>% 
  mutate(porcentaje = 100 * n / sum(n))
                              hospital    n porcentaje
1                     Central Hospital  454   7.710598
2                    Military Hospital  896  15.217391
3                              Missing 1469  24.949049
4                                Other  885  15.030571
5                        Port Hospital 1762  29.925272
6 St. Mark's Maternity Hospital (SMMH)  422   7.167120

Podemos usar geom_bar() con datos agregados y no agregados para obtener prorporciones. El código puede ser un poco más “extraño” con datos individuales, pero la idea es copiar/pegar y adaptar.

Agregando datos

ebola_data %>% 
  count(hospital) %>% 
  mutate(porcentaje = 100 * n / sum(n)) %>% 
  ggplot(aes(x = hospital, y = porcentaje)) + 
  geom_bar(stat = "identity")

Con datos individuales

ebola_data %>% 
  ggplot(aes(x = hospital)) + 
  geom_bar(aes(y = (..count..)/sum(..count..)))

Orden por defecto

ebola_data %>% 
  count(hospital) %>% 
  mutate(porcentaje = 100 * n / sum(n)) %>% 
  ggplot(aes(x = hospital, y = porcentaje)) + 
  geom_col()

Orden arbitrario

ebola_data %>% 
  mutate(
    hospital = fct_relevel(hospital, 
                           "St. Mark's Maternity Hospital (SMMH)", 
                           "Port Hospital", 
                           "Central Hospital",
                           "Military Hospital",
                           "Other",
                           "Missing")
    ) %>% 
  count(hospital) %>% 
  mutate(porcentaje = 100 * n / sum(n)) %>% 
  ggplot(aes(x = hospital, y = porcentaje)) + 
  geom_col()

Podemos querer reordenar las barras de mayor a menoro o viceversa. geom_col() y geom_bar() tiene su propia forma de hacerlo.

Reordenar con geom_bar()

ebola_data %>% 
  ggplot(aes(x = fct_infreq(hospital))) + 
  geom_bar()

Reordenar con geom_col()

ebola_data %>% 
  group_by(hospital) %>% 
  count() %>% 
  ggplot(aes(x = n, y = fct_reorder(hospital, n))) + 
  geom_col()

Podemos etiquetar los gráficos usando la función labs() y sus argumentos.

ebola_data %>% 
  count(hospital) %>% 
  mutate(porcentaje = n / sum(n)) %>% 
  ggplot(aes(x = porcentaje, y = fct_reorder(hospital, porcentaje))) + 
  geom_col() + 
  labs(x = "Porcentaje (%)", 
       y = "Hospital", 
       title = "Distribución de hospitalizaciones de pacientes de Ébola")

También podemos hacer que los colores cambien en base a alguna otra variable

ebola_data %>% 
  count(hospital) %>% 
  mutate(porcentaje = n / sum(n)) %>% 
  ggplot(aes(x = porcentaje, 
             y = fct_reorder(hospital, porcentaje), 
             fill = hospital)) + 
  geom_col() + 
  labs(x = "Porcentaje (%)", 
       y = "Hospital", 
       title = "Distribución de hospitalizaciones de pacientes de Ébola", 
       fill = "Hospital") 

Podemos eliminar la leyenda fácilmente con una capa adicional llamada theme(legend.position=“none”)

ebola_data %>% 
  count(hospital) %>% 
  mutate(porcentaje = n / sum(n)) %>% 
  ggplot(aes(x = porcentaje, 
             y = fct_reorder(hospital, porcentaje), 
             fill = hospital)) + 
  geom_col() + 
  labs(x = "Porcentaje (%)", 
       y = "Hospital", 
       title = "Distribución de hospitalizaciones de pacientes de Ébola", 
       fill = "Hospital")  + 
  theme(legend.position = "none")

Otros gráficos

Gráfico de barras apilada

En vez de graficar varias barras de manera horizontal, las apilamos todas en una sola barra.

Grafico de barras apiladas de frecuencias absolutas

ebola_data %>% 
  count(hospital) %>% 
  ggplot(aes(x = "", y = n, fill = hospital)) + 
  geom_bar(stat = "identity", position = "stack")

Grafico de barras apiladas de frecuencias relativas

ebola_data %>% 
  count(hospital) %>% 
  ggplot(aes(x = "", y = n, fill = hospital)) + 
  geom_bar(stat = "identity", position = "fill")

Gráfico de pie

Es un gráfico de barras empaquetado como una torta o pái; por lo que el código en ggplot primero crea el gráfico de barras y luego lo convierte en torta.

Grafico de barras apiladas de frecuencias absolutas

ebola_data %>% 
  count(hospital) %>% 
  ggplot(aes(x = "", y = n, fill = hospital)) + 
  geom_bar(stat = "identity", width = 1) + 
  coord_polar("y", start = 0)

Grafico de barras apiladas de frecuencias relativas

ebola_data %>% 
  count(hospital) %>% 
  ggplot(aes(x = "", y = n, fill = hospital)) + 
  geom_bar(stat = "identity", position = "fill", width = 1) + 
  coord_polar("y", start = 0)

Lollipop plot

Gráficos que parecen chupetines (“lollipop”). Son equivalentes a las barras. Pueden usarse también para describir la distribución de variables numéricas discretas y deberían preferirse a los histogramas en este caso.

ebola_data %>% 
  count(hospital) %>% 
  ggplot(aes(x = hospital, y = n)) + 
  geom_segment(aes(x = hospital, xend = hospital, y = 0, yend = n)) + 
  geom_point() + 
  theme_minimal()

ebola_data %>% 
  count(hospital) %>% 
  ggplot(aes(x = hospital, y = n)) + 
  geom_segment(aes(x = hospital, xend = hospital, y = 0, yend = n)) + 
  geom_point(color = "blue", alpha = 0.6, size = 4) + 
  theme_minimal() + 
  coord_flip()

Treemap

Es un gráfico básico que muestra mosaicos. El área de cada polígono refleja su frecuencia absoluta o relativa. Se debe usar el paquete {treemap}

library(treemap)
ebola_data %>% 
  count(hospital) %>% 
  treemap(index = "hospital", 
          vSize = "n", 
          type = "index")

Más gráficos

Revisar la web “The R Graph Gallery”:

Ver más: https://r-graph-gallery.com/index.html

Nuestro turno


  • Descargue la carpeta var_cat_grafico_resumen.

  • Abra el proyecto var_cat_grafico_resumen.Rproj y dentro de este, abra el archivo quarto var_cat_resumen.qmd.

  • Siga las instrucciones indicadas en este.

  • Renderice el archivo quarto final.




10:00